package com.hyq.learn.rabbitmq.config;

import com.hyq.learn.rabbitmq.constant.DeadLetterQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Exchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;

/**
 * 死信队列相关配置
 * @author heyuqin
 * @date 2024/8/21 16:43
 */
@Configuration
public class DeadLetterMqConfig implements ApplicationContextAware {

    private static final Logger LOGGER = LoggerFactory.getLogger(DeadLetterMqConfig.class);

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
        for (DeadLetterQueue deadLetterQueue : DeadLetterQueue.values()) {
            createExchange(defaultListableBeanFactory, deadLetterQueue);
            createQueue(defaultListableBeanFactory, deadLetterQueue);
        }
    }

    private void createExchange(DefaultListableBeanFactory defaultListableBeanFactory, DeadLetterQueue deadLetterQueue) {
        Exchange exchange = deadLetterQueue.getExchange();
        if (exchange == null) {
            return;
        }
        GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
        genericBeanDefinition.setBeanClass(Exchange.class);
        genericBeanDefinition.setInstanceSupplier(() -> exchange);

        String beanName = DeadLetterQueue.class.getSimpleName() + "_" + exchange.getName() + "_exchange";
        LOGGER.info("registration bean name {}, exchange {}", beanName, exchange.getName());
        if (!defaultListableBeanFactory.containsBeanDefinition(beanName)) {
            defaultListableBeanFactory.registerBeanDefinition(beanName, genericBeanDefinition);
        }
    }

    private void createQueue(DefaultListableBeanFactory defaultListableBeanFactory, DeadLetterQueue deadLetterQueue) {
        GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
        genericBeanDefinition.setBeanClass(Queue.class);
        Exchange exchange = deadLetterQueue.getExchange();
        Queue queue = QueueBuilder.durable(deadLetterQueue.getQueueName())
                // 设置转发规则
                .withArgument("x-dead-letter-exchange", exchange == null ? "" : exchange.getName())
                .withArgument("x-dead-letter-routing-key", deadLetterQueue.getRoutingKey() == null ? "" : deadLetterQueue.getRoutingKey())
                // 设置队列消息过期时间
                .withArgument("x-message-ttl", deadLetterQueue.getTtl())
                .build();
        genericBeanDefinition.setInstanceSupplier(() -> queue);

        String beanName = DeadLetterQueue.class.getSimpleName() + "_" + deadLetterQueue.getQueueName() + "_queue";
        LOGGER.info("registration bean name {}, queue {}", beanName, deadLetterQueue.getQueueName());
        if (!defaultListableBeanFactory.containsBeanDefinition(beanName)) {
            defaultListableBeanFactory.registerBeanDefinition(beanName, genericBeanDefinition);
        }
    }

}
